/*******************************************************************************

        SSC0143 - Programação Concorrente
        Prof. Julio Cesar Estrela

        T1 - Calculo de PI com 10000000 de casas decimais

        Grupo:

        Daniel de Oliveira Pereira              6427171
        Guilherme Takasawa Yagui                6426698
        Vinícius Marques Stocco                 6427233

        Março de 2013

********************************************************************************
                                Algoritmo de Monte Carlo - versão concorrente
*******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <gmp.h>

#define NUM_ITERACAO 50000 
#define THREADS 1

mpf_t P_dentro; //variável global que armazena o numero de pontos dentro do circulo;
mpf_t P_total;  //variável global que armazena o numero de pontos total;

//gera os pontos randomicamente;
float f_randomico() {
	return ((float)(random())/(float)(RAND_MAX));
}

void* calculo_monte_carlo() {
	float x;
	float y;
	
	x = f_randomico();
	y = f_randomico();
	
	float teste = pow(x,2) + pow(y,2);

	//se o ponto estiver dentro da circunferência, entra no if;
	if (teste <= 1) {
		mpf_add_ui(P_dentro, P_dentro, 1);
		mpf_add_ui(P_total, P_total, 1);
	} else {
		mpf_add_ui(P_total, P_total, 1);
	}
}


int main() {

	FILE *p_file;
    clock_t t; 
    
    mpf_t Pi;  //irá armazenar o valor do Pi;
    mpf_t aux; //auxilia no cálculo do Pi;
    pthread_t thread[THREADS];

    int i,j;

    mpf_init(aux);

    //define a precisão para todas as chamadas de mpf_init;
    mpf_set_default_prec(33300000);   

    mpf_init(Pi);
    mpf_init(P_dentro);
	mpf_init(P_total);

    //marca o clock inicial da execução do algoritmo;
    t = clock();
    
    for(i = 0; i < NUM_ITERACAO; i+=THREADS) {
    
        for(j = 0; j < THREADS; j++) {      
            if(0 != pthread_create(&thread[j], NULL, calculo_monte_carlo, NULL))
            	printf("Erro.\n");
		}        
        
        //espera terminar todas as threads;
        for(j = 0; j < THREADS; j++) {
            if(0 != pthread_join(thread[j], NULL))
            	printf("Erro.\n");
		}
    }
    
    mpf_div(aux, P_dentro, P_total);
    mpf_mul_ui(Pi, aux, 4);

	//calcula o numero clocks necessário para executar o algoritmo;
    t = clock() - t;       
    printf("\nTempo de execucao : %.5f s \n\n", (double) t / CLOCKS_PER_SEC);

   	//abre o arquivo pra escrita e guarda o valor de Pi nele;
   	p_file = fopen("pi_monte_carlo_concorrente.txt", "w");
    mpf_out_str(p_file, 10, 10000000, Pi);
    fclose(p_file);

    return 0;
}
